#pragma once

#include <CEGUI/CEGUIImageset.h>
#include <CEGUI/CEGUISystem.h>
#include <CEGUI/CEGUILogger.h>
#include <CEGUI/CEGUISchemeManager.h>
#include <CEGUI/CEGUIWindowManager.h>
#include <CEGUI/CEGUIWindow.h>
#include <CEGUI/CEGUIPropertyHelper.h>
#include <CEGUI/elements/CEGUICombobox.h>
#include <CEGUI/elements/CEGUIListbox.h>
#include <CEGUI/elements/CEGUIListboxTextItem.h>
#include <CEGUI/elements/CEGUIPushButton.h>
#include <CEGUI/elements/CEGUIScrollbar.h>
#include "OgreCEGUIRenderer.h"
#include "OgreCEGUIResourceProvider.h"

#include "ExampleFrameListener.h"
#include "ExampleApplication.h"

class GuiFrameListener : public ExampleFrameListener, public OIS::KeyListener, public OIS::MouseListener
{
private:
    CEGUI::Renderer* mGUIRenderer;
    bool mShutdownRequested;

public:
    // NB using buffered input, this is the only change
    GuiFrameListener(RenderWindow* win, Camera* cam, CEGUI::Renderer* renderer)
        : ExampleFrameListener(win, cam, true, true, true), 
          mGUIRenderer(renderer),
          mShutdownRequested(false)
    {
		mMouse->setEventCallback(this);
		mKeyboard->setEventCallback(this);
    }

    /// Tell the frame listener to exit at the end of the next frame
    void requestShutdown(void)
    {
        mShutdownRequested = true;
    }

    bool frameEnded(const FrameEvent& evt);
	bool mouseMoved( const OIS::MouseEvent &arg );
	bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id );
	bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id );
	bool keyPressed( const OIS::KeyEvent &arg );
	bool keyReleased( const OIS::KeyEvent &arg );
};

class GuiApplication : public ExampleApplication
{
private:
    CEGUI::OgreCEGUIRenderer* mGUIRenderer;
    CEGUI::System* mGUISystem;
    CEGUI::Window* mEditorGuiSheet;
	CEGUI::Scrollbar* mRed;
	CEGUI::Scrollbar* mGreen;
	CEGUI::Scrollbar* mBlue;
	CEGUI::Window* mPreview; // StaticImage
	CEGUI::Window* mTip;
	CEGUI::Listbox* mList;
	CEGUI::Window* mEditBox;
	typedef std::map<CEGUI::String, CEGUI::String> DescriptionMap;
	DescriptionMap mDescriptionMap;

public:
    GuiApplication();
    ~GuiApplication();

protected:
    // Just override the mandatory create scene method
    void createScene(void);

    // Create new frame listener
    void createFrameListener(void);

    void setupEventHandlers(void);
	void setupEnterExitEvents(CEGUI::Window* win);
	void setupLoadedLayoutHandlers(void);
    CEGUI::Window* createRttGuiObject(void);
    CEGUI::Window* createStaticImageObject(void);
    bool handleQuit(const CEGUI::EventArgs& e);
    bool handleNew(const CEGUI::EventArgs& e);
    bool handleLoad(const CEGUI::EventArgs& e);
    bool handleObjectSelection(const CEGUI::EventArgs& e);
	bool handleColourChanged(const CEGUI::EventArgs& e);
	bool handleAdd(const CEGUI::EventArgs& e);
	bool handleMouseEnters(const CEGUI::EventArgs& e);
	bool handleMouseLeaves(const CEGUI::EventArgs& e);
};
